package com.bzxhh.reflect;

import org.junit.jupiter.api.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class TestCar {

    //1.获取class对象多种方式
    @Test
    public void test01() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //1 类名.class
        Class<Car> clazz1 = Car.class;

        //2 对象.getClass()
        Class<? extends Car> clazz2 = new Car().getClass();

        //3 Class.forName("全路径")
        Class<?> clazz3 = Class.forName("com.bzxhh.reflect.Car");

        //实例化
        Car car = (Car) clazz3.getDeclaredConstructor().newInstance();
        System.out.println(car);
    }

    //2.获取构造方法
    @Test
    public void test02() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class<Car> clazz = Car.class;
        //获取所有public构造方法
        Constructor<?>[] constructors = clazz.getConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println("方法明：" + constructor.getName() + "参数个数：" + constructor.getParameterCount());
        }

        //获取所有public+private方法
        Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }

        //指定有参数创建对象
        //1.构造是public
//        Constructor<Car> c1 = clazz.getConstructor(String.class, int.class, String.class);
//        Car car1 = (Car) c1.newInstance("雅阁", 20, "白色");
//        System.out.println(car1);

        //2.构造是private
        Constructor<Car> c2 = clazz.getDeclaredConstructor(String.class, int.class, String.class);
        c2.setAccessible(true);
        Car car2 = (Car) c2.newInstance("雅阁", 20, "白色");
        System.out.println(car2);

    }

    //3.获取属性
    @Test
    public void test03() throws Exception {
        Class<Car> clazz = Car.class;
        Car car = clazz.getDeclaredConstructor().newInstance();
        //获取所有的public属性
        Field[] fields = clazz.getFields();
        //获取所有的public+private属性
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            if (declaredField.getName().equals("name")) {
                //设置允许访问
                declaredField.setAccessible(true);
                declaredField.set(car, "五菱宏光");
            }
            System.out.println(declaredField);
        }
        System.out.println(car);
    }

    //4.通过反射获取类中所有方法
    @Test
    public void test04() throws Exception {
        Car car = new Car("奔驰", 15, "黑色");
        Class<? extends Car> clazz = car.getClass();
        //1.public方法
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
//            System.out.println(method);
            if (method.getName().equals("toString")) {
                String invoke = (String) method.invoke(car);
                System.out.println("toString方法执行了：" + invoke);
            }
        }

        System.out.println("==========================");

        //2.private方法
        Method[] declaredMethods = clazz.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
//            System.out.println(declaredMethod);
            if (declaredMethod.getName().equals("run")) {
                declaredMethod.setAccessible(true);
                String invoke = (String) declaredMethod.invoke(car);
                System.out.println("run方法执行了：" + invoke);
            }
        }
    }

}
